package main

import (
	"fmt"
	"hello/raft"
	"net"
	"net/rpc"
	"strconv"
)

//节点数量
const (
	NODE_NUM  int    = 3
	NODE_ID   int    = 2
	NODE_ADDR string = "127.0.0.1:8099"

	REMOTE_NODE_ID   int    = 1
	REMOTE_NODE_ADDR string = "127.0.0.1:8088"
)

var RaftNodeSlc []raft.Node

type RaftNode struct {
}

/*
 节点注册
*/
func (this *RaftNode) RegisterForCall(remoteNode raft.Node, registerReply *raft.NodeRegisterReply) error {
	registerReply.Result = true
	//已经注册了的节点列表
	registerReply.RegisterNodeSlc = RaftNodeSlc
	go RemoteRegisterCall(remoteNode)
	fmt.Println(strconv.Itoa(remoteNode.Id) + ">>" + remoteNode.Addr + "注册成功!")
	return nil
}

/*
 远端注册
*/
func RemoteRegisterCall(remoteNode raft.Node) {
	var existFlag = false
	for _, existNode := range RaftNodeSlc {
		if remoteNode.Id == existNode.Id {
			existFlag = true
			break
		}
	}
	if !existFlag {
		nodeRegisterReplyPtr := RegisterCall(remoteNode, RaftNodeSlc[0])
		if nodeRegisterReplyPtr.Result {
			for _, replyNode := range nodeRegisterReplyPtr.RegisterNodeSlc {
				existFlag = false
				for _, raftNode := range RaftNodeSlc {
					if replyNode.Id == raftNode.Id {
						existFlag = true
						break
					}
				}
				if !existFlag {
					//向未注册的节点中注册本节点
					RegisterCall(replyNode, RaftNodeSlc[0])
				}
			}
		}
		//超过3个节点开始选举
		if len(RaftNodeSlc) >= NODE_NUM {
			fmt.Println("raft节点已经准备OK！")
			//初始化
			raft.GlobalRaftPtr = raft.BuildRaft(RaftNodeSlc, RaftNodeSlc[0])
			//开始选举
			raft.GlobalRaftPtr.ElectionDaemon()
		}
	}
}

func RegisterCall(remoteNode raft.Node, selfNode raft.Node) *raft.NodeRegisterReply {
	fmt.Println(strconv.Itoa(selfNode.Id) + "=>向" + remoteNode.Addr + "开始注册")
	rpcClient, err := rpc.Dial("tcp", remoteNode.Addr)
	//关闭连接
	defer rpcClient.Close()
	if err != nil {
		fmt.Println(remoteNode.Addr + "连接失败！=>" + err.Error())
		return nil
	}
	var registerReplyPtr = &raft.NodeRegisterReply{}
	err1 := rpcClient.Call("RaftNode.RegisterForCall", selfNode, registerReplyPtr)
	if err1 != nil {
		fmt.Println(remoteNode.Addr + "远程调用Register失败！=>" + err1.Error())
	}
	RaftNodeSlc = append(RaftNodeSlc, remoteNode)
	//fmt.Println(strconv.Itoa(selfNode.Id)+"=>向"+remoteNode.Addr+"注册完成")
	return registerReplyPtr
}

func init() {
	RaftNodeSlc = append(RaftNodeSlc, raft.Node{
		Addr: NODE_ADDR,
		Id:   NODE_ID,
	})
}

func main() {
	raftNodeStu := new(RaftNode)
	raftStu := new(raft.Raft)
	_ = rpc.Register(raftNodeStu)
	_ = rpc.Register(raftStu)
	listen, err := net.Listen("tcp", NODE_ADDR)
	if err != nil {
		fmt.Println("服务监听失败=>" + err.Error())
		return
	}
	var remoteNode = raft.Node{
		Addr: REMOTE_NODE_ADDR,
		Id:   REMOTE_NODE_ID,
	}
	go RemoteRegisterCall(remoteNode)

	for {
		//等待节点的连接
		conn, err := listen.Accept()
		if err != nil {
			fmt.Println(conn.RemoteAddr().String() + "连接失败!")
			continue
		}
		go rpc.ServeConn(conn)
	}
}
